package com.darwin.darwinIsometric.core
{
	import com.darwin.darwinBitmapEngine.core.Canvas;
	import com.darwin.darwinBitmapEngine.core.INode;
	import com.darwin.darwinBitmapEngine.core.Node;
	import com.darwin.darwinBitmapEngine.view.SceneView;
	import com.darwin.darwinIsometric.core.isoConst.IsoTryResult;
	import com.darwin.darwinIsometric.core.isoConst.IsoType;
	import com.darwin.darwinIsometric.core.isoInterface.ISort;
	import com.darwin.darwinIsometric.data.IsoWorldData;
	import com.darwin.darwinIsometric.events.IsoMouseEvent;
	import com.darwin.darwinIsometric.events.IsoWorldEvent;
	import com.darwin.darwinIsometric.map.IsoMap;
	import com.darwin.darwinIsometric.pathfinding.MapGrid;
	import com.darwin.darwinIsometric.utils.IsoSort;
	import com.darwin.darwinIsometric.utils.IsoUtils;
	import com.darwin.darwinNameSpace.darwin;
	import com.darwin.darwinUtils.BitmapDataTool;
	
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	import flash.utils.Timer;


	/**
	 * 2.5D场景对象
	 * @author vanCopper
	 */
	public class IsoWorld extends EventDispatcher
	{
		/**
		 * 场景数据 
		 */		
		private var _isoWorldData:IsoWorldData;
		
		private var _contentRect:Rectangle;// = new Rectangle();
		
		private var _sceneDic:Dictionary = new Dictionary();
		
		private var _contentXChanged:Boolean;
		private var _contentYChanged:Boolean;
		
		
		private var _sceneXNum:int = 0;
		private var _sceneZNum:int = 0;
		

		/**
		 * 如果is9Scene的值为true 那么 xNum,zNum 代表9屏中一屏的大小</br>
		 * 地图将根据这个大小来切割地图 否则 代表场景大小
		 * @param sceneView
		 * @param xNum 2.5D中 一个屏幕 x轴上 格子数
		 * @param zNum 2.5D中 一个屏幕 z轴上 格子数
		 * @param size
		 * @param is9Scene 是否支持地图9分屏
		 */		
		public function IsoWorld(sceneView:SceneView,xNum:int = 30,zNum:int = 30,size:int = 16,isClose9Scene:Boolean = false,isNeedStaticBackGround:Boolean = false,isNeedDynamicBackGround:Boolean = false)
		{
			_sceneView = sceneView;
			_sceneView.isoWorld = this;
			
			_floorIsoList = new IsoList();
			_objectIsoList = new IsoList();
			
			
			_floorLayer = new Canvas(1,1,true);
			_floorLayer.setNodeListType(_floorIsoList);
			_gridLayer = new Canvas(1,1,true);
			_objectLayer = new Canvas(1,1,true);
			_objectLayer.setNodeListType(_objectIsoList);
			
			var $vector:Vector.<Canvas> = new Vector.<Canvas>();
			
			$vector.push(_floorLayer);
			$vector.push(_gridLayer);
			$vector.push(_objectLayer);
			
			//检测背景
			if(isNeedDynamicBackGround){
				_dynamicBackgroundLayer = new Canvas(1,1,true);
				$vector.unshift(_dynamicBackgroundLayer);
			}
			if(isNeedStaticBackGround){
				_staticBackgroundLayer = new Canvas(1,1,true);
				$vector.unshift(_staticBackgroundLayer);
			}
			
			_map = new IsoMap();
			_sorter = new IsoSort(size);
			_sceneView.addCanvasList($vector);
			
			_xNum = xNum;
			_zNum = zNum;
			if(isClose9Scene)
			{
				sceneXNum = _xNum;
				sceneZNum = _zNum;
			}
			_size = size;
			initWorld();
//			scale = 0.5;
		}
		
		protected var _staticBackgroundLayer:Canvas;//禁止背景层
		protected var _dynamicBackgroundLayer:Canvas;//动态跟随背景层
		private var _floorLayer:Canvas;//地板层
		private var _gridLayer:Canvas;//网格层
		private var _objectLayer:Canvas;//物件层
		
		private var _floorIsoList:IsoList;//地板iso列表
		private var _objectIsoList:IsoList;//物件iso列表
		
		private var _map:IsoMap;//世界地图

		private var _sceneView:SceneView;//呈现场景的视图
		
		private var _isoGrid:IsoGrid;
		private var _size:int;
		private var _xNum:int;
		private var _zNum:int;
		private var _sorter:ISort;
		
		
		public function getIsoList():Vector.<IsoObject>
		{
			return _map.getIsoList();
		}
		

		/**
		 *	排序算法实例(需要实现ISort接口) 
		 * <BR>默认使用：IsoSort
		 */
		public function get sorter():ISort
		{
			return _sorter;
		}

		/**
		 * @private
		 */
		public function set sorter(value:ISort):void
		{
			_sorter = value;
		}

		/**
		 *	2.5d世界单个网格大小 
		 * @return 
		 * 
		 */
		public function get size():int
		{
			return _size;
		}

		/**
		 * 世界网格 
		 */
		public function get isoGrid():IsoGrid
		{
			return _isoGrid;
		}

		/**
		 * @private
		 */
		public function set isoGrid(value:IsoGrid):void
		{
			_isoGrid = value;
		}

		
		/**
		 * 注册已有场景数据的场景 
		 * @param x 2.5D中 场景开始点的x索引
		 * @param z 2.5D中 场景开始点的z索引
		 * 
		 */		
		public function registerSceneFlag(x:Number,z:Number):void
		{
			if(!_sceneDic)
			{
				_sceneDic = new Dictionary();
			}
			var posXY:String = "" + x + ":" + z;
			_sceneDic[posXY] = true;
		}
		
		/**
		 * 从已注册场景数据中移除 指定场景标记 
		 * @param x 2.5D中 场景开始点的x索引
		 * @param z 2.5D中 场景开始点的z索引
		 * 
		 */		
		public function removeSceneFlag(x:Number,z:Number):void
		{
			var posXY:String = "" + x + ":" + z;
			if(_sceneDic[posXY])
			{
				delete _sceneDic[posXY];
			}
		}
		
		/**
		 * 获取寻路数组 
		 * @return 
		 * 
		 */		
		public function getMapGrid():MapGrid
		{
			var mapGrid:MapGrid;
			var isEmp:Boolean = true;
			
			for(var i:* in _sceneDic)
			{
				isEmp = false;
				break;
			}
			if(_sceneDic)
			{
//				var sceneArr:Array = checkSceneFlag();
				if(is9Scene)
				{
					checkSceneFlag();
					var sceneArr:Array = current9SceneArr;
					var indexArr:Array = sceneArr[0];
					var startX:Number = indexArr[0] * _xNum;
					var startZ:Number = indexArr[1] * _zNum;
					mapGrid = _map.getMapGrid(_xNum*3,_zNum*3,startX,startZ);
				}else
				{
					mapGrid = _map.getMapGrid(sceneXNum,sceneZNum);
				}
			}else
			{
				mapGrid = _map.getMapGrid(_xNum,_zNum);
			}
			
			return mapGrid;
		}
		
		/**
		 * 获取指定区域的mapGrid mapGrid对应的原始引用 每次对mapGrid</br>
		 * 的操作都会对应改变原始mapGrid
		 * @param startX
		 * @param startZ
		 * @param rectW
		 * @param rectH
		 * @return 
		 * 
		 */		
		public function getRectMapGrid(startX:int,startZ:int,rectW:int,rectH:int):MapGrid
		{
			return _map.getMapGrid(rectW,rectH,startX,startZ);
		}
		
		
		/**
		 * 根据舞台全局坐标 得到该坐标所在格子的格子坐标 
		 * @param x 全局x坐标
		 * @param y 全局y坐标
		 * 
		 */		
		public function getGridPoint3D(x:Number,y:Number):IsoPosition
		{
			var vx:Number = x/scale - contentX;
			var vy:Number = y/scale - contentY;
			var pos:Point3D = IsoUtils.screenToIso(new Point(vx,vy));
			var isoPosition:IsoPosition = new IsoPosition(Math.floor(pos.x/size),Math.floor(pos.z/size));
			return isoPosition;
		}
		
		/**
		 * 根据舞台坐标 获取精确的世界坐标 
		 * @param x
		 * @param y
		 * @return 
		 * 
		 */		
		public function getIsoWorldPoint3D(x:Number,y:Number):Point3D
		{
			var vx:Number = x/scale - contentX;
			var vy:Number = y/scale - contentY;
			var pos:Point3D = IsoUtils.screenToIso(new Point(vx,vy));
			return pos;
		}
		
		/**
		 * 根据格子坐标获取对应的全局坐标 
		 * @param isoPostion
		 * @return 
		 * 
		 */		
		public function getGlobalPoint(isoPostion:IsoPosition):Point
		{
			if(!isoPostion){return null;}
			
			var vx:Number = isoPostion.x*size;
			var vy:Number = isoPostion.z*size;
			
			var pos:Point = IsoUtils.isoToScreen(new Point3D(vx,0,vy));
			pos.x = pos.x/scale + contentX;
			pos.y = pos.y/scale + contentY;
			return pos;
		}
		
		
		/**
		 * 场景鼠标事件处理 
		 * @param x 全局x坐标
		 * @param y 全局y坐标
		 * @param type 鼠标事件类型
		 * 
		 */		
		public function mouseEventHandler(x:Number,y:Number,type:String):void
		{
			var isoObjectLayer:INode;
			var isoFloorLayer:INode;
			var isoMouseEvent:IsoMouseEvent;
			if(type == MouseEvent.CLICK)
			{
				isoObjectLayer = _objectLayer.setClick(x,y);
				isoFloorLayer = _floorLayer.setClick(x,y);
				
				if(isoObjectLayer)
				{
					isoMouseEvent = new IsoMouseEvent(IsoMouseEvent.ISO_MOUSE_CLICK)
					isoMouseEvent.nodeTarget = isoObjectLayer;
					isoMouseEvent.nodeContainer = isoObjectLayer.parentContainer;
					this.dispatchEvent(isoMouseEvent);
				}else if(isoFloorLayer)
				{
					isoMouseEvent = new IsoMouseEvent(IsoMouseEvent.ISO_MOUSE_CLICK)
					isoMouseEvent.nodeTarget = isoFloorLayer;
					isoMouseEvent.nodeContainer = isoFloorLayer.parentContainer;
					this.dispatchEvent(isoMouseEvent);
				}else 
				{
					this.dispatchEvent(new IsoMouseEvent(IsoMouseEvent.ISO_MOUSE_CLICK_SPACE));
				}
			}else if(type == MouseEvent.MOUSE_MOVE)
			{
				isoMouseEvent = new IsoMouseEvent(IsoMouseEvent.ISO_MOUSE_MOVE)
				isoObjectLayer = _objectLayer.setMouseMove(x,y);
				
					
				if(isoObjectLayer)
				{
					isoMouseEvent.nodeTarget = isoObjectLayer;
					isoMouseEvent.nodeContainer = isoObjectLayer.parentContainer;
					this.dispatchEvent(isoMouseEvent);
					return;
				}
				isoFloorLayer = _floorLayer.setMouseMove(x,y);
				if(isoFloorLayer)
				{
					isoMouseEvent.nodeTarget = isoFloorLayer;
					isoMouseEvent.nodeContainer = isoFloorLayer.parentContainer;
					this.dispatchEvent(isoMouseEvent);
					return;
				}
				this.dispatchEvent(isoMouseEvent);
			}else if(type == MouseEvent.MOUSE_OUT)
			{
				this.dispatchEvent(new IsoMouseEvent(IsoMouseEvent.ISO_MOUSE_OUT));
			}else if(type == MouseEvent.MOUSE_DOWN)
			{
				isoMouseEvent = new IsoMouseEvent(IsoMouseEvent.ISO_MOUSE_DOWN)
				isoObjectLayer = _objectLayer.setMouseDown(x,y);
				isoFloorLayer = _floorLayer.setMouseDown(x,y);
				
				if(isoObjectLayer)
				{
					isoMouseEvent.nodeTarget = isoObjectLayer;
					isoMouseEvent.nodeContainer = isoObjectLayer.parentContainer;
				}else if(isoFloorLayer)
				{
					isoMouseEvent.nodeTarget = isoFloorLayer;
					isoMouseEvent.nodeContainer = isoFloorLayer.parentContainer;
				}
				this.dispatchEvent(isoMouseEvent);
			}else if(type == MouseEvent.MOUSE_UP)
			{
				this.dispatchEvent(new IsoMouseEvent(IsoMouseEvent.ISO_MOUSE_UP));
			}
		}
		
		/**
		 * 当前9屏 地图数据索引 
		 */		
		public var current9SceneArr:Array = [];
		private var _loopi:int = -1;
		private var _loopj:int = 1;
		/**
		 * 根据当前 contentX contentY 计算出当前屏 返回需要缓存的但未注册的地图索引
		 * 
		 * @return 
		 * 
		 */		
		public function checkSceneFlag():Array
		{
			current9SceneArr.length = 0;
			var contentPoint:Point = new Point(-contentX+this.width/2,-contentY+this.height/2);
			checkPoint(contentPoint);
			var point3D:Point3D = IsoUtils.screenToIso(contentPoint);
			var tempX:Number = point3D.x;// + sceneW/2;
			var tempZ:Number = point3D.z;// + sceneH/2;
//			var posX:int = tempX/(_xNum*_size);
//			var posZ:int = tempZ/(_zNum*_size);
			var posX:int = Math.floor(tempX/(_xNum*_size));
			var posZ:int = Math.floor(tempZ/(_zNum*_size));
//			trace(posX + ":" + posZ);
			var returnArr:Array = [];
			/*for(var i:int = -1; i<= 1; i++)
			{
				for(var j:int = -1; j<=1; j++)
				{*/
			for(var i:int = _loopi; i<= _loopj; i++)
			{
				for(var j:int = _loopi; j<=_loopj; j++)
				{
					
					var targetX:int = posX + i;
					var targetZ:int= posZ + j;
					current9SceneArr.push([targetX,targetZ]);
					var posXY:String = "" + targetX + ":" + targetZ;
					if(!_sceneDic[posXY])
					{
						returnArr.push([targetX,targetZ]);
					}
				}
			}
//			trace(returnArr);
			return returnArr;
		}
		
		private var pointNode:Node;
		//TODO 测试方法 检查中心点
		private function checkPoint(contentPoint:Point):void
		{
//			trace(contentPoint);
			if(!pointNode)
			{
				var cir:Sprite = new Sprite();
				cir.graphics.beginFill(0xFFFF00);
				cir.graphics.drawRect(0,0,20,20);
				cir.graphics.endFill();
				var testBitmapData:BitmapData = BitmapDataTool.getBitmapData(cir);
				pointNode = new Node(testBitmapData);
				_objectLayer.addNode(pointNode);
			}
			pointNode.x = contentPoint.x;
			pointNode.y = contentPoint.y;
		}
		
		/**
		 * 增加一个iso对象到world
		 */
		public function addToWorld(isoObject:IsoObject):IsoObject
		{
			isoObject.parentWorld = this;
			if(isoObject.isoType == IsoType.FLOOR)
			{
				_floorSorted = false;
				_floorLayer.addNode(isoObject);
			}else{
				_objectSorted = false;
				_objectLayer.addNode(isoObject);
			}
			_map.addIsoObject(isoObject);
			clearUpIsoObject(isoObject);
			return isoObject;
		}
		
		
		/**
		 * 保存每屏幕的isoObject对象 _isoObjectSceneDic["0:1"] = [isoObject1,isoObject2]; 
		 */		
		private var _isoObjectSceneDic:Dictionary = new Dictionary();
		
		public function clearUpIsoObject(isoObject:IsoObject,isRemove:Boolean = false):void
		{
			var point3D:Point3D = isoObject.postion3D;
			var tempX:Number = point3D.x;
			var tempZ:Number = point3D.z;
			var posX:int = Math.floor(tempX/(_xNum*_size));
			var posZ:int = Math.floor(tempZ/(_zNum*_size));
			var index:String = "" + posX + ":" + posZ;
//			trace(tempX,tempZ,":::::::index::::::::",index);
			if(_isoObjectSceneDic[index])
			{
				var tempArr:Array = _isoObjectSceneDic[index];
				if(isRemove)
				{
					var removeIndex:int = tempArr.indexOf(isoObject);
					if(removeIndex != -1)
					{
						tempArr.splice(removeIndex,1);
					}
				}else
				{
					if(tempArr.indexOf(isoObject) == -1)
					{
						tempArr.push(isoObject);
					}
				}
			}else
			{
				if(!isRemove)
				{
					_isoObjectSceneDic[index] = [isoObject];
				}
			}
		}
		
		/**
		 * 整理回收场景物件
		 * 
		 */		
		private function clearUpScene():void
		{
			var indexArr:Array = [];
			for (var i:int = 0; i < current9SceneArr.length; i++) 
			{
				var tempArr:Array = current9SceneArr[i];
				indexArr.push(tempArr.join(":"));
			}
			
			for(var key:String in _isoObjectSceneDic)
			{
				var isoObjectArr:Array = _isoObjectSceneDic[key];
				var isoObject:IsoObject;
				if(indexArr.indexOf(key) != -1)
				{
					for (var j:int = 0; j < isoObjectArr.length; j++) 
					{
						isoObject = isoObjectArr[j];
						if(isoObject.parentWorld == null)
						{
							addToWorld(isoObject);
						}
					}
				}else
				{
					for (var k:int = 0; k < isoObjectArr.length; k++) 
					{
						isoObject = isoObjectArr[k];
						if(isoObject && isoObject.parentWorld)
						{
							removeFromWorld(isoObject,false);
						}
					}
				}
			}
		}
		
		/**
		 * 清理指定屏幕的所有物件 
		 * @param indexX 屏幕x索引
		 * @param indexZ 屏幕z索引
		 * 
		 */		
		public function removeIsoObjectFormScene(indexX:int,indexZ:int):void
		{
			var index:String = "" + indexX + ":" + indexZ;
			if(_isoObjectSceneDic[index])
			{
				var isoObjectArr:Array = _isoObjectSceneDic[index];
				
				while (isoObjectArr.length>0) 
				{
					var isoObject:IsoObject = isoObjectArr[0];
					if(isoObject)
					{
						if(isoObject.parentWorld)
						{
							removeFromWorld(isoObject,true);
						}else{
							clearUpIsoObject(isoObject,true);
							isoObject.dispose();
						}
					}
				}
				delete _isoObjectSceneDic[index];
			}
		}
		
		/**
		 * 从world中移除一个iso对象
		 * @param isoObject
		 * @param isClearUp 是否从已保存的地图数据中清除 IsoObject实例
		 */
		public function removeFromWorld(isoObject:IsoObject,isClearUp:Boolean = true):IsoObject
		{
			if(isoObject.isoType == IsoType.FLOOR)
			{
				_floorLayer.removeNode(isoObject);
			}else{
				_objectLayer.removeNode(isoObject);
			}
			_map.removeIsoObject(isoObject);
			if(isClearUp)
			{
				clearUpIsoObject(isoObject,true);
				isoObject.dispose();
			}
			isoObject.parentWorld = null;
			return isoObject;
		}
		
		/**
		 * 从world中移除所有IsoObject对象</br>
		 * 被移除的IsoObject会调用 IsoObject.dispose 
		 * 
		 */		
		public function removeAllIsoObjectFromWorld():void
		{
			var isoArr:Vector.<IsoObject> = getIsoList();
			for (var i:int = 0; i < isoArr.length; i++) 
			{
				var isoObject:IsoObject = isoArr[i];
				if(isoObject.parentWorld!=this)//在移除的过程中可能外部已经把这个列表里的某项给移除了。
					continue;
				removeFromWorld(isoObject);
			}
		}
		
		/**
		 * 通过2.5D 坐标获取该坐标下的物件 
		 * @param x 2.5D中x轴坐标
		 * @param z 2.5D中z轴坐标
		 * @param type 物件类型 默认IsoType.OBJECT ...
		 * @return 
		 * 
		 */		
		public function getObjectListByXZ(x:int,z:int,type:String = IsoType.OBJECT):Array
		{
			if(_map != null)
			{
				return _map.getObjectListByXZ(x,z,type);	
			}
			return null;
		}
		
		/**
		 * 获取2.5D中指定区域下 物件列表 
		 * @param startX
		 * @param startZ
		 * @param endX
		 * @param endZ
		 * @param type 物件类型 默认IsoType.OBJECT ...
		 * @return 
		 * 
		 */		
		public function getObjectListByRange(startX:int,startZ:int,endX:int,endZ:int,type:String = IsoType.OBJECT):Array
		{
			if(_map != null)
			{
				return _map.getObjectListByRange(startX,startZ,endX,endZ,type);
			}
			return null;
		}
		
		/**
		 * 标记一个iso对象的位置被改变
		 * @param isoObject 改变的iso对象
		 */
		public function markChange(isoObject:IsoObject):IsoObject
		{
			if(isoObject.isoType == IsoType.OBJECT)
			{
				_objectSorted = false;
			}else{
				_floorSorted = false;
			}
			clearUpIsoObject(isoObject);
			return _map.addChangeIsoObject(isoObject);
		}
		
		
		/**
		 * 物件排序标记
		 */
		private var _objectSorted:Boolean = false;
		
		/**
		 * 地板排序标记
		 */
		private var _floorSorted:Boolean = false;
		
		/**
		 * 对isoWorld中的对象进行排序
		 */
		public function sort():void
		{
			if(_objectSorted == false)
			{
				sortCanvas(_objectLayer,IsoType.OBJECT);
				_objectSorted = true;
			}
			if(_floorSorted == false)
			{
				sortCanvas(_floorLayer,IsoType.FLOOR);
				_floorSorted = true;
			}
			
		}
		
		
		/**
		 * 对一个画布中的显示对象进行排序
		 */
		private function sortCanvas(canvas:Canvas,type:String):void
		{
			//			var $i:Number = getTimer();
			use namespace darwin;
			var $changeDic:Dictionary = _map.changeObjectDic;
			var $changeCount:int = _map.changeObjectCount;
			var $insertList:Array = [];
			var $nodeList:IsoList = canvas.nodeList as IsoList;
			
			if($nodeList != null && sorter != null)
			{
				if($changeCount >= 40)//有变化的物件超过40个,改用全排序
				{
					sorter.fullSort($nodeList.list);
				}else{
					for each(var iso:IsoObject in $changeDic) 
					{
						if(iso.isoType == type)
						{
							$nodeList.list.splice($nodeList.list.indexOf(iso),1);
							$insertList.push(iso);
						}
					}
					if($insertList.length > 0)
					{
						sorter.insertSort($nodeList.list,$insertList);//插入排序
					}else{
						sorter.fullSort($nodeList.list);//全排序
					}
				}
			}
			//			trace("sortCanvas耗费时间:",getTimer() - $i,"ms");
		}
		
	
		
		
		private var _grid9nodeList:Vector.<Node> = new Vector.<Node>();
		private var _grid9Dic:Dictionary = new Dictionary();
		private var _grid9Flag:Boolean;

		
		/**
		 * 打开9屏的格子 
		 * 
		 */		
		public function open9SceneGrid():void
		{
			_grid9Flag = true;
			update9SceneGrid();
		}
		
		/**
		 * 更新9屏格子 
		 * 
		 */		
		public function update9SceneGrid():void
		{
			if(!_grid9Flag){return;};
			var w:int = _xNum*_size;
			var h:int = _zNum*_size;
			
			for(var i:int = 0; i<current9SceneArr.length; i++)
			{
				if(_grid9Dic[current9SceneArr[i].toString()]){continue;};
				
				_grid9Dic[current9SceneArr[i].toString()] = true;
				var gx:int = current9SceneArr[i][0];
				var gz:int = current9SceneArr[i][1];
				var node:Node = IsoGrid.getGrid(w,h,gx,gz);
				var pos3D:Point3D = new Point3D(gx*w,0,gz*h);
				var pos:Point = IsoUtils.isoToScreen(pos3D);
				node.x += pos.x;
				node.y = pos.y;
				_gridLayer.addNode(node);
				_grid9nodeList.push(node);
			}
		}
		
		/**
		 * 关闭9屏的格子 
		 * 
		 */		
		public function close9SceneGrid():void
		{
			_grid9Flag = false;
			_grid9Dic = new Dictionary();
			if(_grid9nodeList && _grid9nodeList.length)
			{
				for(var i:int=0; i<_grid9nodeList.length; i++)
				{
					var node:Node = _grid9nodeList[i];
					if(node && node.parentContainer)
					{
						node.parentContainer.removeNode(node);
					}
				}
			}
		}
		
		/**
		 * 显示地图格子 
		 * @param xNum
		 * @param zNum
		 * @param gridColor
		 * 
		 */		
		public function showMapGrid(xNum:int,zNum:int,gridColor:uint = 0xFF0000,thickness:Number = 2):void
		{
			hideMapGrid();			
			_isoGrid = new IsoGrid(xNum,zNum,size,true,gridColor,thickness);
			_gridLayer.addNodeAt(_isoGrid,0);
		}
		
		/**
		 * 隐藏地图格子 
		 * 
		 */		
		public function hideMapGrid():void
		{
			if(_isoGrid && _isoGrid.parentContainer)
			{
				_isoGrid.parentContainer.removeNode(_isoGrid);
			}
		}
		
		/**
		 * 用于保存已显示的网格 
		 */		
		private var _gridDic:Dictionary = new Dictionary();
		/**
		 * 显示物件格子 
		 * @param isoObject
		 * @param showAll
		 * @param gridColor
		 * 
		 */		
		public function showGrid(isoObject:IsoObject,showAll:Boolean = false,gridColor:uint = 0xFF0000,thickness:Number = 1):void
		{
			if(isoObject)
			{
				var xNum:int = isoObject.floorWidth/size;
				var zNum:int = isoObject.floorHeight/size;
				var postion3D:Point3D = isoObject.postion3D;
				var showIsoGrid:IsoGrid = new IsoGrid(xNum,zNum,size,showAll,gridColor,thickness);
				_gridDic[isoObject] = showIsoGrid;
				_gridLayer.addNode(showIsoGrid);
				updateGrid(isoObject,postion3D);
			}
		}
		
		/**
		 * 隐藏格子 
		 * 
		 */		
		public function hideGrid(isoObject:IsoObject):void
		{
			var showIsoGrid:IsoGrid = _gridDic[isoObject];
			if(showIsoGrid && showIsoGrid.parentContainer)
			{
				_gridLayer.removeNode(showIsoGrid);
				delete _gridDic[isoObject];
			}
		}
		
		/**
		 * 将已有的格子移动到指定位置 
		 * @param postion3D
		 * 
		 */		
		public function moveGrid(isoObject:IsoObject,postion3D:Point3D,gridColor:uint = 0):void
		{
			var showIsoGrid:IsoGrid = _gridDic[isoObject];
			if(showIsoGrid && showIsoGrid.parentContainer)
			{
				updateGrid(isoObject,postion3D,gridColor);
			}
		}
		
		private function updateGrid(isoObject:IsoObject,postion3D:Point3D,gridColor:uint = 0):void
		{
			var endPostion3D:Point3D = new Point3D();
			endPostion3D.x = postion3D.x - _size*IsoGrid._OFF_SIZE/2;
			endPostion3D.z = postion3D.z - _size*IsoGrid._OFF_SIZE/2;
			var pos:Point = IsoUtils.isoToScreen(endPostion3D);
			var showIsoGrid:IsoGrid = _gridDic[isoObject];
			if(gridColor)
			{
				showIsoGrid.changeGridColor(gridColor);
			}
			showIsoGrid.x = pos.x;
			showIsoGrid.y = pos.y;
//			_gridLayer.render();
		}
		
		private var _startDragIsoObjPoint:Point3D;
		private var _startDragIsoObject:IsoObject;
		private var _dragIsoObjectFlag:Boolean;
		//当取消diy时 被拖动isoObject的原始位置
		private var _originalIsoObjectPoint:Point3D;
		/**
		 * 开始拖动世界中的一个显示对象 
		 * @param isoObject
		 * @param startPoint 全局平面坐标
		 */		
		public function startDragIsoObject(isoObject:IsoObject,startPoint:Point):void
		{
			if(isoObject)
			{
				_startDragIsoObject = isoObject;
				startPoint.x = startPoint.x/scale;
				startPoint.y = startPoint.y/scale;
//				startPoint.x = startPoint.x*scale;
//				startPoint.y = startPoint.y*scale;
//				_testPoint = startPoint;
				var newPoint:Point = new Point(startPoint.x - contentX,startPoint.y - contentY);
				_startDragIsoObjPoint = IsoUtils.screenToIso(newPoint);
				_originalIsoObjectPoint = isoObject.postion3D;
				_dragIsoObjectFlag = true;
			}
		}
		
		public function updateDragIsoObject(endPoint:Point):void
		{
//			trace(_dragIsoObjectFlag,_dragFlag);
			endPoint.x = endPoint.x/scale;
			endPoint.y = endPoint.y/scale;
//			endPoint.x = endPoint.x*scale;
//			endPoint.y = endPoint.y*scale;
			if(_dragIsoObjectFlag && !_dragFlag)
			{
				endPoint = new Point(endPoint.x - contentX,endPoint.y - contentY);
				var tempPoint3D:Point3D = IsoUtils.screenToIso(endPoint);
				var vx:Number = tempPoint3D.x - _startDragIsoObjPoint.x;
				var vz:Number = tempPoint3D.z - _startDragIsoObjPoint.z;
				
				var endX:int = Math.floor(vx/_size)*_size;
				var endZ:int = Math.floor(vz/_size)*_size;
//				if(_scaleChanged)
//				{
//					endX = endX*scale;
//					endZ = endZ*scale;
//					
//					_originalIsoObjectPoint.x = _originalIsoObjectPoint.x*scale;
//					_originalIsoObjectPoint.y = _originalIsoObjectPoint.y*scale;
//					_scaleChanged = false;
//				}
				var endPoint3D:Point3D = new Point3D(_originalIsoObjectPoint.x + endX,_originalIsoObjectPoint.y,_originalIsoObjectPoint.z + endZ);
				moveIsoObject(_startDragIsoObject,endPoint3D);
			}
		}
		
		/**
		 * 停止拖动，如果isCancel = true 那么就代表没有移动该物件
		 * 物件会回到原始位置 
		 * @param isCancel
		 * 
		 */		
		public function stopDragIsoObject(isCancel:Boolean = false):void
		{
			_dragIsoObjectFlag = false;
			if(isCancel)
			{
				if(_startDragIsoObject)
				{
					moveIsoObject(_startDragIsoObject,_originalIsoObjectPoint);
				}
			}
		}
		
		
		private var _startPoint:Point;
		private var _dragFlag:Boolean;
		/**
		 * 设置场景拖动开始点
		 * startPoint 是相对于某一坐标系的 x,y值 
		 * @param startPoint
		 * 
		 */		
		public function startDrag(startPoint:Point):void
		{
			if(startPoint)
			{
				_startPoint = startPoint;
			}
		}
		
		private var _draging:Boolean = false;
		/**
		 * 设置场景拖动结束点 并执行拖动
		 * endPoint 是相对于某一坐标系(与startPoint一至的坐标系)的x,y值 
		 * @param endPoint
		 * 
		 */		
		public function updateDrag(endPoint:Point):void
		{
			if(endPoint)
			{
				var offX:Number = endPoint.x - _startPoint.x;
				var offY:Number = endPoint.y - _startPoint.y;
				contentX += offX/scale;
				contentY += offY/scale;
				_startPoint = endPoint;
				if(!_dragFlag)
				{
					dispatchEvent(new IsoWorldEvent(IsoWorldEvent.ISO_START_DRAG));
					_dragFlag = true;
				}
			}
		}
		
		/**
		 * 停止场景拖动 
		 * 
		 */		
		public function stopDrag():void
		{
			if(_dragFlag)
			{
				dispatchEvent(new IsoWorldEvent(IsoWorldEvent.ISO_STOP_DRAG));
				_dragFlag = false;
			}
		}
		
		/**
		 * 尝试在场景中放下一个IsoObject对象 
		 * @param testIsoObject
		 * @param tryX 全局X坐标
		 * @param tryY 全局Y坐标
		 * @return 
		 * 
		 */		
		public function tryHandler(tryIsoObject:IsoObject,tryX:Number = NaN,tryY:Number = NaN):IsoTryResult
		{
			var tryResult:IsoTryResult = new IsoTryResult();
			
			if(tryIsoObject != null)
			{
				if(tryIsoObject.isoType == IsoType.OBJECT)
				{
					tryResult = tryHandlerObject(tryIsoObject,tryX,tryY);
				}
			}
			
			return tryResult;
		}
		
		/**
		 * 测试放置一般建筑物 
		 * @param isoObject
		 * @param tryX 
		 * @param tryY
		 * @return 
		 * 
		 */		
		private function tryHandlerObject(isoObject:IsoObject,tryX:Number = NaN,tryY:Number = NaN):IsoTryResult
		{
			var tryResult:IsoTryResult = new IsoTryResult();
//			trace("isoObject.........;;;;;;;;",isoObject.isoPosition,isoObject.maxIsoPosition,tryX,tryY);
			//判断是否超出边界 矩形区域内的建筑是否可被叠加
			var maxIsoPosition:IsoPosition;
			var isoPosition:IsoPosition;
			if(tryX.toString() == "NaN" && tryY.toString() == "NaN")
			{
				maxIsoPosition = isoObject.maxIsoPosition;
				isoPosition = isoObject.isoPosition;
			}else{
				var tryPoint3D:Point3D = getIsoWorldPoint3D(tryX,tryY);
				var $isox:int = Math.floor(tryPoint3D.x / isoObject.size);
				var $isoz:int = Math.floor(tryPoint3D.z / isoObject.size);
				var $isomx:int = Math.floor((tryPoint3D.x + isoObject.floorWidth-1) / isoObject.size);
				var $isomz:int = Math.floor((tryPoint3D.z + isoObject.floorHeight-1) / isoObject.size);
				isoPosition = new IsoPosition($isox,$isoz);
				maxIsoPosition = new IsoPosition($isomx,$isomz);
			}
			var limitScene:Boolean = false;
			if(sceneXNum != 0 && sceneZNum != 0)
			{
				//场景拥有大小限制
				limitScene = true;
			}
			
			if(limitScene)
			{
				if(isoPosition.x < 0 || isoPosition.x > sceneXNum || isoPosition.z < 0 || isoPosition.z > sceneZNum)
				{
					tryResult.isSucess = false;
					tryResult.isoPosition = isoPosition;
					return tryResult;
				}
			}
			var isoObjectArr:Array = getObjectListByRange(isoPosition.x,isoPosition.z,maxIsoPosition.x,maxIsoPosition.z);
			var spliceIndex:int = isoObjectArr.indexOf(isoObject);
			while(spliceIndex != -1)
			{
				isoObjectArr.splice(spliceIndex,1);
				spliceIndex = isoObjectArr.indexOf(isoObject);
			}
			
			var len:int = isoObjectArr.length;
			if(len == 0)
			{
				tryResult.isSucess = true;
				tryResult.isoPosition = isoPosition;
			}else
			{
				if(isoObject.canPlaced)
				{
					var index:int;
					for(index = 0; index < len; index++)
					{
						var tempIsoObject:IsoObject = isoObjectArr[index];
						if(!tempIsoObject.isContainer)
						{
							break;
						}
					}
					if(index != len)
					{
						tryResult.isSucess = false;
						tryResult.isoPosition = isoPosition;
					}else
					{
						tryResult.isSucess = true;
						tryResult.isoPosition = isoPosition;
					}
				}else
				{
					tryResult.isSucess = false;
					tryResult.isoPosition = isoPosition;
				}
			}
			return tryResult;
		}
		
		
		
		/**
		 * 世界场景是否可拖动 默认场景可拖动
		 */
		public function get isAbleDrag():Boolean
		{
			return _sceneView.isAbleDrag;
		}
		
		/**
		 * @private
		 */
		public function set isAbleDrag(value:Boolean):void
		{
			_sceneView.isAbleDrag = value;
		}
		
		/**
		 * 更新场景位置 
		 * @param x
		 * @param y
		 * 
		 */		
		private function updateContentXY(x:Number,y:Number):void
		{
			if(_dynamicBackgroundLayer)
			{
				_dynamicBackgroundLayer.contentY = y;
				_dynamicBackgroundLayer.contentX = x;
			}
			
			_objectLayer.contentX = x;
			_floorLayer.contentX = x;
			_gridLayer.contentX = x;
			_gridLayer.contentY = y;
			_objectLayer.contentY = y;
			_floorLayer.contentY = y;
		}
		
		
		
		/**
		 *动态背景移动 
		 * 
		 */
		protected function dynamicBgUpdate():void{
			if(_dynamicBackgroundLayer){
				_dynamicBackgroundLayer.x = _dynamicBackgroundLayer.contentX + _dynamicBackgroundOffsetX;
				_dynamicBackgroundLayer.y = _dynamicBackgroundLayer.contentY + _dynamicBackgroundOffsetY;
			}
			
		}
		
		/**
		 * 初始化世界 
		 * 
		 */		
		private function initWorld():void
		{
			if(_sceneView.stage)
			{
				_sceneView.stage.addEventListener(Event.ENTER_FRAME,frameRender);
			}
		}
		
		/**
		 * 每帧执行一次场景的渲染 
		 * @param event
		 * 
		 */		
		protected function frameRender(event:Event):void
		{
			render();
			// 检查是否有新的场景需要加载
			if(_contentYChanged || _contentXChanged /*|| _scaleChanged*/)
			{
				if(is9Scene && !_dragFlag)
				{
					var sceneIndexArr:Array = checkSceneFlag();
					clearUpScene();
					if(sceneIndexArr.length)
					{
						this.dispatchEvent(new IsoWorldEvent(IsoWorldEvent.ISO_MAP_CHANGED,sceneIndexArr));
					}
					_contentXChanged = false;
					_contentYChanged = false;
				}
			}
		}
		
		/**
		 * 移动IsoObject 到指定位置 
		 * @param isoObject
		 * @param point3D
		 * 
		 */		
		public function moveIsoObject(isoObject:IsoObject,point3D:Point3D):void
		{
			if(isoObject && isoObject.parentContainer)
			{
				clearUpIsoObject(isoObject,true);
				isoObject.postion3D = point3D;
				clearUpIsoObject(isoObject);
			}
		}
		
		
		private var _dynamicBackgroundOffsetX:Number = 0;
		private var _dynamicBackgroundOffsetY:Number = 0;
		/**
		 *添加对象到背景层 
		 * @param node
		 * @param type 0:远景（禁止不动） 1：近景（跟随拖拽一起）
		 * 
		 */
		public function addToBackGround(bitmapData:BitmapData,type:int=0,offsetX:Number=0,offsetY:Number=0):void{
			if(type == 0){
				if(_staticBackgroundLayer){
					_staticBackgroundLayer.bitmapData = bitmapData;
					_staticBackgroundLayer.x = offsetX;
					_staticBackgroundLayer.y = offsetY;
				}
			}else{
				if(_dynamicBackgroundLayer){
					_dynamicBackgroundLayer.bitmapData = bitmapData;
					_dynamicBackgroundOffsetX = offsetX;
					_dynamicBackgroundOffsetY = offsetY;
					_dynamicBackgroundLayer.x = offsetX;
					_dynamicBackgroundLayer.y = offsetY;
				}
			}
			
		}
		
		/**
		 *删除所有背景层 
		 * 
		 */
		public function removeAllBgFromWorld():void{
			if(_staticBackgroundLayer){
				_staticBackgroundLayer.bitmapData = null;
			}
			if(_dynamicBackgroundLayer){
				_dynamicBackgroundLayer.bitmapData = null;
			}
		}
		
		/**
		 * 对IsoWorld中的对象进行呈现
		 */
		public function render():void
		{
			if(_worldResize)
			{
				if(_staticBackgroundLayer){
					_staticBackgroundLayer.canvasWidth = width;
					_staticBackgroundLayer.canvasHeight = height;
				}
				if(_dynamicBackgroundLayer){
					_dynamicBackgroundLayer.canvasWidth = width;
					_dynamicBackgroundLayer.canvasHeight = height;
				}
				_floorLayer.canvasWidth = width;
				_floorLayer.canvasHeight = height;
				_gridLayer.canvasWidth = width;
				_gridLayer.canvasHeight = height;
				_objectLayer.canvasWidth = width;
				_objectLayer.canvasHeight = height;
				_worldResize = false;
			}
			sort();//先对显示列表做个排序
			_objectLayer.render();
			_gridLayer.render();
			_floorLayer.render();

			if(_dynamicBackgroundLayer){
				dynamicBgUpdate();
			}
		}
		
		
		private var _contentX:Number = 0;

		/**
		 * IsoWorld中内容的可见的起始点x,
		 * 改变contentX，contentY将使得看到场景的不同部份
		 * @return 
		 */
		public function get contentX():Number
		{
			return _contentX;
		}

		public function set contentX(value:Number):void
		{
//			trace("X.",value);
			if(checkContentX(value))
			{
				_contentX = value;
				updateContentXY(_contentX,contentY);
				_contentXChanged = true;
			}
		}
		
		private function checkContentX(value:Number):Boolean
		{
			if(contentRect == null){return true;}
//			trace(contentRect);
			if(value >= contentRect.x && value <= contentRect.width + contentRect.x )
			{
				return true;
			}
			return false;
		}
		
		private function checkContentY(value:Number):Boolean
		{
			if(contentRect == null){return true;}
			if(value >= contentRect.y && value <= contentRect.height + contentRect.y)
			{
				return true;
			}
			return false;
		}
		
		private var _contentY:Number = 0;
		/**
		 * IsoWorld中内容的可见起始点y，
		 * 改变contentX，contentY将使得看到场景的不同部份
		 * @return 
		 */
		public function get contentY():Number
		{
			return _contentY;
		}

		public function set contentY(value:Number):void
		{
//			trace("Y.",value);
			if(checkContentY(value))
			{
				_contentY = value;
				updateContentXY(contentX,_contentY);
				_contentYChanged = true;
			}
		}

		/**
		 * @return 内容的宽度
		 */
		public function get contentWidth():Number
		{
			return 0;
		}

		/**
		 * @return 内容的高度
		 */
		public function get contentHeight():Number
		{
			return 0;
		}
		
		
		private var _worldResize:Boolean = false;
		private var _width:Number;
		/**
		 * 改变isoWorld可见宽度
		 * @return 宽度值
		 */
		public function get width():Number
		{
			return _width;
		}
		
		public function set width(value:Number):void
		{
			_width = value;
			_worldResize = true;
		}
		
		
		private var _height:Number;
		/**
		 * 改变isoWorld可见高度
		 * @return 高度值
		 */
		public function get height():Number
		{
			return _height;
		}

		public function set height(value:Number):void
		{
			_height = value;
			_worldResize = true;
		}
		
		
		
		private var _x:Number = 0;

		/**
		 * isoWorld的x坐标值
		 * @return 
		 */
		public function get x():Number
		{
			return _x;
		}

		public function set x(value:Number):void
		{
			_x = value;
		}
		
		private var _y:Number = 0;

		/**
		 * isoWorld的y坐标值
		 * @return 
		 */
		public function get y():Number
		{
			return _y;
		}

		public function set y(value:Number):void
		{
			_y = value;
		}
		
		private var _scaleChanged:Boolean = false;
		
		private var _scale:Number = 1;
		
		/**
		 * 对画布缩放
		 */
		public function get scale():Number
		{
			return _scale;
		}
		
		public function set scale(value:Number):void
		{
			_scale = value;
			if(_staticBackgroundLayer){
				_staticBackgroundLayer.scale = value;
			}
			if(_dynamicBackgroundLayer){
				_dynamicBackgroundLayer.scale = value;
			}
			
			_objectLayer.scale = value;
			_floorLayer.scale = value;
			_gridLayer.scale = value;
			_scaleChanged = true;
		}
		
		
		
		/**
		 * 设置整个场景数据 
		 * @param value
		 * 
		 */		
		public function set isoWorldData(value:Object):void
		{
			_isoWorldData = IsoWorldData.parseData(value);
			if(_isoWorldData)
			{
				initWorld();
			}
		}

		/**
		 *  世界的可视区域
		 */
		public function get contentRect():Rectangle
		{
			return _contentRect;
		}

		/**
		 * @private
		 */
		public function set contentRect(value:Rectangle):void
		{
			_contentRect = value;
		}

		/**
		 * 设置一个格子的通行状态。默认情况下，isoWorld的通行状态由所添加进来的物件决定的。
		 * 如果除此之外需要额外设置通行状态可使用setWalkable方法。
		 * 在自定义的地图中可以将整个isoWorld使用setWalkable方法进行设置
		 */
		public function setWalkable(x:int,z:int,value:int):void
		{
			_map.setWalkable(x,z,value);
		}

		/**
		 * 场景2.D中 x轴上 格子数 
		 */
		public function get sceneXNum():int
		{
			return _sceneXNum;
		}

		/**
		 * @private
		 */
		public function set sceneXNum(value:int):void
		{
			_sceneXNum = value;
		}

		/**
		 * 场景2.5D中 z轴上 格子数 
		 */
		public function get sceneZNum():int
		{
			return _sceneZNum;
		}

		/**
		 * @private
		 */
		public function set sceneZNum(value:int):void
		{
			_sceneZNum = value;
		}

		/**
		 * 如果设置了场景的大小 则代表关闭了9屏功能 
		 * @return 
		 * 
		 */		
		private function get is9Scene():Boolean
		{
			if(sceneXNum != 0 && sceneZNum != 0)
			{
				return false;
			}
			return true;
		}

		/**
		 * 动态背景偏移量 
		 */
		public function get dynamicBackgroundOffsetX():Number
		{
			return _dynamicBackgroundOffsetX;
		}

		/**
		 * @private
		 */
		public function set dynamicBackgroundOffsetX(value:Number):void
		{
			_dynamicBackgroundOffsetX = value;
			dynamicBgUpdate();
		}

		public function get dynamicBackgroundOffsetY():Number
		{
			return _dynamicBackgroundOffsetY;
		}

		public function set dynamicBackgroundOffsetY(value:Number):void
		{
			_dynamicBackgroundOffsetY = value;
			dynamicBgUpdate();
		}

		public function get floorIsoList():IsoList
		{
			return _floorIsoList;
		}

		public function get objectIsoList():IsoList
		{
			return _objectIsoList;
		}


	}
}